1 /* 2 * Hunt - a framework for web and console application based on Collie using Dlang development 3 * 4 * Copyright (C) 2015-2017 Shanghai Putao Technology Co., Ltd 5 * 6 * Developer: HuntLabs 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 12 module hunt.view.parser; 13 14 import std.stdio; 15 import std.conv; 16 import std.algorithm; 17 import std.variant; 18 import std.array; 19 import std.string; 20 import std.typetuple; 21 22 import hunt.view; 23 24 abstract class Expression 25 { 26 public string Evaluate(ViewContext ctx = null); 27 } 28 class Constant : Expression 29 { 30 public string value; 31 public this(string value) 32 { 33 this.value = value; 34 } 35 override public string Evaluate(ViewContext ctx = null ) 36 { 37 return " str ~= `" ~ value ~ "`;"; 38 } 39 } 40 41 class VariableReference : Expression 42 { 43 public string value; 44 public this(string value) 45 { 46 this.value = value; 47 } 48 override public string Evaluate(ViewContext ctx = null) 49 { 50 return " str ~= std.conv.to!string(" ~ value ~ ");"; 51 } 52 } 53 class ExecuteBlock : Expression 54 { 55 public string value; 56 public this(string value) 57 { 58 this.value = value; 59 } 60 override public string Evaluate(ViewContext ctx = null) 61 { 62 return value; 63 } 64 } 65 class Operation : Expression 66 { 67 public Expression left; 68 public Expression value; 69 public Expression right; 70 public this(Expression left,Expression value,Expression right) 71 { 72 this.left = left; 73 this.value = value; 74 this.right = right; 75 } 76 override public string Evaluate(ViewContext ctx = null) 77 { 78 auto x = left.Evaluate(ctx); 79 auto y = right.Evaluate(ctx); 80 return x ~ value.Evaluate(ctx) ~ y; 81 } 82 } 83 Expression strToTree(string str,int s,int t) 84 { 85 if(s >= t)return new Constant(null); 86 87 bool findVar = false; 88 bool findExe = false; 89 int ves,vet; 90 static import std.algorithm; 91 for(int i = s;i<t;i++) 92 { 93 if((i+2 <= t) && canFind(["{{","{%"],str[i..i+2])) 94 { 95 ves = i; 96 if(str[i+1] == '{') findVar = true; 97 else findExe = true; 98 for(int k = i;k<t;k++) 99 { 100 if(canFind(["}}","%}"],str[k..k+2])) 101 { 102 vet = k+2; 103 break; 104 } 105 } 106 break; 107 } 108 } 109 if(ves==0 && !findVar && !findExe)return new Constant(str[s..t]); 110 if(findVar && ves==s && vet==t)return new VariableReference(str[ves+2 .. vet-2]); 111 if(findExe && ves==s && vet==t)return new ExecuteBlock(str[ves+2 .. vet-2]); 112 if(str[ves .. ves+2] == "{%") 113 return new Operation(strToTree(str,s,ves),new ExecuteBlock(str[ves+2 .. vet-2]),strToTree(str,vet,t)); 114 else 115 return new Operation(strToTree(str,s,ves),new VariableReference(str[ves+2 .. vet-2]),strToTree(str,vet,t)); 116 } 117 118 class Parser 119 { 120 public string str; 121 public string FunHeader = ` 122 static string TempleFunc(ViewContext var,CompiledTemple* ct = null){ 123 static import std.conv; 124 string render(string _view_file)(){ 125 return render_with!_view_file(var); 126 } 127 string render_with(string _view_file)(ViewContext var = null){ 128 auto r = display!(_view_file)(); 129 return r.toString(var); 130 } 131 string yield(){ 132 return ct.toString(var); 133 } 134 string str; 135 with(var){ 136 `; 137 public string FunFooter = ` 138 } 139 return str; 140 }`; 141 public Expression stt = null; 142 public ViewContext ctx = null; 143 this(string str) 144 { 145 this.str = str; 146 this.stt = strToTree(str,0,str.length.to!int); 147 } 148 override string toString() 149 { 150 return FunHeader ~ stt.Evaluate(ctx) ~ FunFooter; 151 } 152 } 153 154 unittest 155 { 156 auto p = new Parser(```{% import std.stdio; %}<div>{{value["name"]}}```); 157 assert(p.stt.Evaluate() == " str ~= ``; import std.stdio; str ~= `<div>`; str ~= std.conv.to!string(value[\"name\"]); str ~= ``;"); 158 }